<template>
  <el-select v-loadmore:[popperClassName]="onLoadmore" :popper-class="popperClassName" v-model="formData" filterable remote :remote-method="(queryStr)=>getOptions(queryStr, 'remote')" @blur="onBlur" clearable @keydown.enter.native="enter" v-bind="$attrs" :placeholder="comPlaceholder">
    <el-option v-show="false" v-for="item in defaultOptions" :key="item.value"  :label="item[comOptionsConfig.label]" :value="item[comOptionsConfig.value]"></el-option>
    <el-option v-for="item in comOptions" :key="item.value" :label="item[comOptionsConfig.label]" :value="item[comOptionsConfig.value]">
      <slot :row="item" :col="comOptionsConfig"></slot>
    </el-option>
  </el-select>
</template>

<script>
import { uniqueId } from "lodash";
import { createLoading } from "@/utils";
export default {
  props: {
    value: {
      type: [String, Number, Array],
      default: "",
    },
    apiParams: {
      type: Function,
      default: () => () => ({}),
    },
    defaultOptions: {
      type: Array,
      default: () => ([])
    }
  },
  name: "yySelectLoadMore",
  directives: {
    loadmore: {
      inserted(el, binding) {
        const { arg, value } = binding;
        // 获取element-ui定义好的scroll盒子
        const SELECTDOWN_DOM = el.querySelector(
          `.${arg} .el-select-dropdown__wrap`
        );
        SELECTDOWN_DOM?.addEventListener("scroll", function () {
          const CONDITION =
            this.scrollHeight - Math.ceil(this.scrollTop) <=
            this.clientHeight + 1;
          if (CONDITION && this.scrollTop !== 0) {
            value && value();
          }
        });
      },
    },
  },
  computed: {
    formData: {
      get() {
        return this.value;
      },
      set(val) {
        this.$emit("input", val);
      },
    },
    comPlaceholder() {
      return this.$attrs.placeholder || "";
    },
    comOptions() {
      if (this.$attrs.options?.length) {
        return this.$attrs.options;
      }
      return this.options;
    },
    comOptionsConfig() {
      return Object.assign(
        { label: "label", value: "value" },
        this.$attrs.optionsConfig || {}
      );
    },
  },
  data() {
    return {
      popperClassName: uniqueId("popper-class_"),
      options: [],
      loading: false,
      condition: {
        totalPage: 0,
        curTotal: 0,
        pageSize: 15,
        currPage: 1,
        query: "",
      },
    };
  },
  methods: {
    onBlur() {
      if (this.condition.query) {
        this.condition.query = "";
        this.getOptions();
      }
    },
    onLoadmore() {
      const { totalPage, currPage } = this.condition;
      if (totalPage == currPage || this.loading) {
        return;
      }
      this.condition.currPage += 1;
      this.getOptions(this.condition.query, "scroll");
    },
    enter() {
      this.$emit("enter");
    },
    async getOptions(query, type) {
      if (this.loading) return;
      if (this.$attrs.api) {
        // 远端搜索
        if (type == "remote") {
          this.condition.currPage = 1;
          this.condition.query = query || "";
          this.condition.totalPage = 0;
          this.options = [];
        } else if (type == "scroll") {
          // 滚动搜索
        } else {
          // 初次加载
          this.condition.currPage = 1;
          this.condition.pageSize = 15;
          this.condition.totalPage = 0;
        }
        this.loading = createLoading(
          "加载数据中",
          document.querySelector(`.${this.popperClassName}`)
        );
        try {
          const res = await this.$attrs.api(this.apiParams(this.condition));
          const { totalPage, list } = res;
          this.condition.totalPage = totalPage;
          const { value, label } = this.comOptionsConfig;
          list.forEach((c) => {
            const flag = this.comOptions.some((d) => d[value] === c[value]);
            if (!flag) {
              const objs = c;
              objs[value] = c[value];
              objs[label] = c[label];
              this.options.push(objs);
            }
          });
        } catch (err) {
        } finally {
          this.loading.close();
          this.loading = null;
        }
      }
    },
  },
  mounted() {
    this.getOptions();
  },
};
</script>

<style>
</style>